/*
 * LDIR
 * 
 * LDIR, a GPS cartography application built for Let's Do It Romania eco 
 * campaign.
 * Copyright (C) 2010 Genera Software <office@generasoftware.com>
 * 
 * http://generasoftware.com/
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 */
#include <e32base.h>
#include <e32cmn.h>
#include <e32debug.h>
#include <e32std.h>
#include "GPSPositionData.h"
#include "GPSLocator.h"
#include "Globals.h"

//RDebug::Print(_L("%d\n"), __LINE__);


CGPSLocator::CGPSLocator() :
	CActive( EPriorityStandard ), // Standard priority
		iPositionInfo( NULL ), iPositionData( NULL ), iPositionModuleId(
			TUid::Null() )
	{
	}

CGPSLocator* CGPSLocator::NewLC()
	{
	CGPSLocator* self = new ( ELeave ) CGPSLocator();
	CleanupStack::PushL( self );
	self->ConstructL();
	return self;
	}

CGPSLocator* CGPSLocator::NewL()
	{
	CGPSLocator* self = CGPSLocator::NewLC();
	CleanupStack::Pop(); // self;
	return self;
	}

void CGPSLocator::ConstructL()
	{
	User::LeaveIfError( iPositionServer.Connect() );
	CActiveScheduler::Add( this ); // Add to scheduler

	TPositionFieldIdList list =
		{
			EPositionFieldHorizontalSpeed,
			EPositionFieldTrueCourse,
			EPositionFieldMagneticCourse,
			EPositionFieldHeading,
			EPositionFieldMagneticHeading,
			EPositionFieldSatelliteNumInView,
			EPositionFieldSatelliteNumUsed,
			EPositionFieldNone
		};
	iPositionInfo = HPositionGenericInfo::NewL();
	iPositionInfo->SetRequestedFields( list );
	iPositionData = CGPSPositionData::NewL();
	}

CGPSLocator::~CGPSLocator()
	{
	Stop();
	iPositionServer.Close();
	delete iPositionInfo;
	delete iPositionData;
	}

CGPSPositionData& CGPSLocator::PositionData()
	{
	return *iPositionData;
	}

void CGPSLocator::DoCancel()
	{
	iPositioner.CancelRequest( EPositionerNotifyPositionUpdate );
	}

void CGPSLocator::StartL()
	{
	Stop();
	//RDebug::Print(_L("%d\n"), __LINE__);
	User::LeaveIfError( iPositioner.Open( iPositionServer ) );
	//RDebug::Print(_L("%d\n"), __LINE__);
	User::LeaveIfError(
		iPositioner.SetRequestor( CRequestor::ERequestorService,
			CRequestor::EFormatApplication, KAppName ) );
	RequestPositionL();
	}

void CGPSLocator::Stop()
	{
	Cancel();
	iPositioner.Close();
	iPositionModuleId = TUid::Null();
	}

void CGPSLocator::RunL()
	{
	switch ( iStatus.Int() )
		{
		case KErrNone:
		case KPositionPartialUpdate:
			{
			SetPositionModuleInfo();
			iPositionData->SetPositionInfoL( iPositionModuleInfo, iPositionInfo );
			if ( KErrNone == iStatus.Int() )
				{
				PositionUpdated( *iPositionData );
				}
			else
				{
				PositionUpdatedPartial( *iPositionData );
				}
			iPositionInfo->ClearPositionData();
			RequestPositionL();
			break;
			}
		case KPositionQualityLoss:
			{
			SetPositionModuleInfo();
			iPositionInfo->ClearPositionData();
			QualityLoss();
			RequestPositionL();
			break;
			}
		case KErrTimedOut:
			{
			SetPositionModuleInfo();
			iPositionInfo->ClearPositionData();
			TimedOut();
			RequestPositionL();
			break;
			}
		case KErrCancel:
			{
			break;
			}
		case KErrArgument:
		case KErrAccessDenied:
		default:
			iPositionInfo->ClearPositionData();
			PositionError( iStatus.Int() );
			//            CAknQueryDialog* dialog1 = CAknQueryDialog::NewL();
			//            if ( dialog1->ExecuteLD( R_TTGP_DIALOG_QUERY_NOTITLE_YESNO,
			//                *iMsgLBSError1 ) )
			//                {
			//                StartL();
			//                }
			//            else
			//                {
			//                CAknConfirmationNote *note =
			//                    new ( ELeave ) CAknConfirmationNote( EFalse );
			//                note->ExecuteLD( *iMsgLBSError2 );
			//                }
			break;
		}
	}

TInt CGPSLocator::RunError( TInt aError )
	{
	RequestPositionL();
	return KErrNone;
	}

void CGPSLocator::SetPositionModuleInfo()
	{
	TBuf<128> moduleName;
	if ( iPositionModuleId == TUid::Null() && iPositionInfo->ModuleId()
		!= TUid::Null() )
		{
		iPositionModuleId = iPositionInfo->ModuleId();
		iPositionServer.GetModuleInfoById( iPositionModuleId,
			iPositionModuleInfo );
		iPositionModuleInfo.GetModuleName( moduleName );
		PositioningMethod( moduleName );
		}
	else if ( iPositionModuleId != iPositionInfo->ModuleId()
		&& iPositionInfo->ModuleId() != TUid::Null() )
		{
		iPositionModuleId = iPositionInfo->ModuleId();
		iPositionServer.GetModuleInfoById( iPositionModuleId,
			iPositionModuleInfo );
		iPositionModuleInfo.GetModuleName( moduleName );
		PositioningMethod( moduleName );
		}
	else
		{
		return;
		}
	}

void CGPSLocator::RequestPositionL()
	{
	const TTimeIntervalMicroSeconds KUpdateInterval( 1000000 );
	const TTimeIntervalMicroSeconds KTimeOut( 2000000 );
	const TTimeIntervalMicroSeconds KMaxUpdateAge( 0 );
	TPositionUpdateOptions options;
	options.SetUpdateInterval( KUpdateInterval );
	options.SetUpdateTimeOut( KTimeOut );
	options.SetMaxUpdateAge( KMaxUpdateAge );
	options.SetAcceptPartialUpdates( ETrue );
	User::LeaveIfError( iPositioner.SetUpdateOptions( options ) );
	iPositioner.NotifyPositionUpdate( *iPositionInfo, iStatus );
	SetActive();
	}
